package myJs.detailInfo

import cats.effect.IO
import japgolly.scalajs.react.ScalaFnComponent
import japgolly.scalajs.react.util.EffectCatsEffect._
import japgolly.scalajs.react.vdom.all._
import myJs.Implicits._
import myJs.api.Api
import myJs.cps.BootstrapTableCp
import myJs.cps.BootstrapTableCp.Column
import myJs.myPkg.Hooks._
import myJs.myPkg.reactBootstrap._
import myJs.tool.Pojo._
import myJs.tool.Tool
import shared.pojo.Browse._
import upickle.default._

import scala.collection.immutable.SeqMap
import scala.scalajs.js

/** Created by yz on 28/11/2023
  */
object IndelInterSnpCp {

  case class Props(id: String, hasChange: Boolean => IO[Unit])

  val Component = ScalaFnComponent[Props] { props =>

    val fileNamePrefix = s"indel.intergenic.info"

    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (columns, setColumns) = useState(List.empty[Column])

    object FTool {

      def tbFmt(field: String) = (v: ujson.Value, row: ujson.Obj) => {
        field match {
          case "query_ID" =>
            a(href := s"https://www.ncbi.nlm.nih.gov/nuccore/${v.str}", cursor.pointer, target := "_blank", v.str)
          case "ref" =>
            a(href := s"https://www.ncbi.nlm.nih.gov/protein/${v.str}", cursor.pointer, target := "_blank", v.str)
          case "gene_id" =>
            a(
              href := s"https://www.ncbi.nlm.nih.gov/gene/?term=${v.str}",
              cursor.pointer,
              target := "_blank",
              v.str
            )
          case _ => span(v.myStr)()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def refreshBasicData = {
        val request = GetFileData.Request(id = props.id, fileName = s"${fileNamePrefix}.xls")
        Api.browse.getMummerFileData(request).flatMap { response =>
          val curDatas = response.array
          val map = response.map
          val basicColumns = map.map { case (k, v) =>
            val searchKind = v match {
              case _ => TextSearch
            }
            val title = v match {
              case _ => v
            }
            val fmt = FTool.tbFmt(v)
            val comVF = FTool.comVFmt(v)
            val optionMap = searchKind match {
              case _ => SeqMap[String, String]()
            }
            val operable = k match {
              case _ => true
            }
            val questionMap = SeqMap(
              "query_ID" -> "InDel 在样品中的 scaffold 或者 contig 名称",
              "InDel_type" -> "InDel 类型（Insertion 或者 Deletion）",
              "InDel_start" -> "InDel 在样品中的起始位点",
              "InDel_end" -> "InDel 在样品中的终止位点",
              "ref" -> "参考序列名称",
              "ref_start" -> "InDel 在参考序列中的起始位点",
              "ref_end" -> "InDel 在参考序列中的终止位点",
              "Base" -> "插入或者缺失的碱基序列",
              "Fr" -> "样品序列和参考序列 Lastz 比对的方向",
              "distance" -> "InDel 与距离其最近的基因的距离",
              "gene_start" -> "基因的起始位点",
              "gene_end" -> "基因的终止位点",
              "gene_strand" -> "Gene 序列方向（“+”表示正链， “-”表示负链）",
              "gene_id" -> "基因名称",
            )
            val titleE = v match {
              case x if (questionMap.isDefinedAt(x)) => {
                span(
                  v,
                  " ", {
                    val popover = Popover(id = "popover-basic")(
                      Popover.Header("说明"),
                      Popover.Body(
                        questionMap(v)
                      )
                    ).rawElement
                    OverlayTrigger(
                      placement = "auto",
                      trigger = js.Array("hover", "focus"),
                      overlay = popover
                    )(
                      span(
                        a(`type` := "button", i(className := "fa fa-question-circle"))
                      )
                    )
                  }
                )()
              }
              case x if !(List("OTU ID").contains(x)) =>
                span(
                  v
                )()
              case x => span(v)()
            }
            Column(
              field = k,
              title = title,
              operable = true,
              searchKind = searchKind,
              formatter = fmt,
              comVF = comVF,
              optionMap = optionMap,
              titleE = titleE
            )
          }.toList
          val curColumns = basicColumns
          val datas = curDatas.map(x => writeJs(x).transform(reader[ujson.Obj]))
          setColumns(curColumns) >>
            setDatas(datas) >>
            props.hasChange(curColumns.nonEmpty)
        }
      }

      def downloadData = (filterDatas: List[ujson.Obj], showColumnNames: List[String]) =>
        IO {
          val downloadColumnNames = showColumnNames.removeAll(List("state", "operate"))
          val filedTitleMap = columns.map(x => (x.field, x.title)).toSeqMap
          val headers = downloadColumnNames.map(x => filedTitleMap(x))
          val contents = filterDatas.map { obj =>
            downloadColumnNames.map { k =>
              obj.value(k).myStr
            }
          }
          val arrays = (headers :: contents)
          Tool.downloadXlsx(s"${fileNamePrefix}.xlsx", arrays)
        }

    }

    useEffect(
      {
        FTool.refreshBasicData
      },
      List(props.id)
    )

    val exportDatas = List(
      ExportData("XLSX", onClick = FTool.downloadData)
    )

    div(
      BootstrapTableCp
        .Props(
          columns = columns,
          datas = datas,
          showExport = true,
          exportData = exportDatas,
          search = true
        )
        .render
    )

  }

  def apply(id: String, hasChange: Boolean => IO[Unit]) = {
    Component(Props(id, hasChange))
  }

}
